
/***************************************************

  @file tca8418_keypad_gpio_interrupt.ino

  This is an example for the Adafruit TCA8418 Keypad Matrix / GPIO Expander Breakout

  Designed specifically to work with the Adafruit TCA8418 Keypad Matrix
  ----> https://www.adafruit.com/products/XXXX

  These Keypad Matrix use I2C to communicate, 2 pins are required to
  interface.
  The Keypad Matrix has an interrupt pin to provide fast detection
  of changes.

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

// NeoPixel Ring simple sketch (c) 2013 Shae Erisson
// Released under the GPLv3 license to match the rest of the
// Adafruit NeoPixel library

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

// Which pin on the Arduino is connected to the NeoPixels?
#define PIN 14 // On Trinket or Gemma, suggest changing this to 1

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 70 // Popular NeoPixel ring size

Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

#define ROWS 10
#define COLS 7
const char *keymap[ROWS][COLS] = {
    {"`", "1", "2", "3", "4", "5", "6"},
    {"Tab", "Q", "W", "E", "R", "T", "Y"},
    {"Fn", "A", "S", "D", "F", "G", "H"},
    {"^", "@", "&", "Z", "X", "C", "V"},
    {"帮助", "电源", "发音", "报时", "英汉", "名片", "计算"},
    {"7", "8", "9", "0", "_", "=", "BSP"},
    {"U", "I", "O", "P", "[", "]", "\\"},
    {"H", "J", "K", "L", ";", "'", "Enter"},
    {"B", "N", "M", ",", ".", "/", "↑"},
    {"行程", "游戏", "时间", "网络", "space", "up", "down"}};

const uint8_t new_keymap2[10][7] = {
    {69, 68, 67, 66, 65, 64, 63},
    {55, 54, 53, 52, 51, 50, 49},
    {41, 40, 39, 38, 37, 36, 35},
    {27, 26, 25, 24, 23, 22, 21},
    {13, 12, 11, 10, 9, 8, 7},
    {62, 61, 60, 59, 58, 57, 56},
    {48, 47, 46, 45, 44, 43, 42},
    {34, 33, 32, 31, 30, 29, 28},
    {20, 19, 18, 17, 16, 15, 14},
    {6, 5, 4, 3, 2, 1, 0}};

const uint8_t new_keymap[10][7] = {
    {0, 1, 2, 3, 4, 5, 6},
    {14, 15, 16, 17, 18, 19, 20},
    {28, 29, 30, 31, 32, 33, 34},
    {42, 43, 44, 45, 46, 47, 48},
    {56, 57, 58, 59, 60, 61, 62},
    {7, 8, 9, 10, 11, 12, 13},
    {21, 22, 23, 24, 25, 26, 27},
    {35, 36, 37, 38, 39, 40, 41},
    {49, 50, 51, 52, 53, 54, 55},
    {63, 64, 65, 66, 67, 68, 69}};

#include <Adafruit_TCA8418.h>

Adafruit_TCA8418 keypad;

//  typical Arduino UNO
const int IRQPIN = 11;

volatile bool TCA8418_event = false;

void TCA8418_irq()
{
  TCA8418_event = true;
}

void setup_tca8418()
{

  // Serial.println(__FILE__);

  if (!keypad.begin(TCA8418_DEFAULT_ADDR, &Wire1))
  {
    Serial.println("keypad not found, check wiring & pullups!");
    while (1)
      ;
  }
  pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
  pixels.setBrightness(10);
  // configure the size of the keypad matrix.
  // all other pins will be inputs
  keypad.matrix(7, 10);

  //  install interrupt handler
  //  going LOW is interrupt
  pinMode(IRQPIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(IRQPIN), TCA8418_irq, CHANGE);

  //  flush pending interrupts
  keypad.flush();
  //  enable interrupt mode
  keypad.enableInterrupts();
}

void loop_tca8418()
{
  //  CHECKING THE STAT REGISTER
  static uint32_t last = 0;
  if (millis() - last > 1000)
  {
    last = millis();
    int x = keypad.readRegister(TCA8418_REG_INT_STAT);
    Serial.print("STAT:\t");
    Serial.print(x, HEX);
    Serial.print("\t");
    Serial.println(keypad.available(), HEX);
  }

  //  IRQ TO HANDLE?
  if (TCA8418_event == true)
  {
    //  CHECK WHICH INTERRUPTS TO HANDLE
    int intStat = keypad.readRegister(TCA8418_REG_INT_STAT);
    if (intStat & 0x02)
    {
      //  reading the registers is mandatory to clear IRQ flag
      //  can also be used to find the GPIO changed
      //  as these registers are a bitmap of the gpio pins.
      keypad.readRegister(TCA8418_REG_GPIO_INT_STAT_1);
      keypad.readRegister(TCA8418_REG_GPIO_INT_STAT_2);
      keypad.readRegister(TCA8418_REG_GPIO_INT_STAT_3);
      //  clear GPIO IRQ flag
      keypad.writeRegister(TCA8418_REG_INT_STAT, 2);
    }

    if (intStat & 0x01)
    {
      //  datasheet page 16 - Table 2
      int keyCode = keypad.getEvent();
      if (keyCode & 0x80)
        Serial.print("PRESS\t ");
      else
      {
        Serial.print("RELEASE\t ");
        pixels.clear(); // Set all pixel colors to 'off'
        pixels.show();
      }

      //  map keyCode to GPIO nr.
      keyCode &= 0x7F;

      if (keyCode > 96) //  GPIO
      {
        //  process  gpio
        keyCode -= 97;
        Serial.print(keyCode);
        Serial.println();
      }
      else
      {
        //  process  matrix
        keyCode--;
        int col = keyCode / 10;
        int row = keyCode % 10;
        // Serial.print(col);
        // Serial.print("\t ");
        // Serial.print(row);
        // Serial.println();

        Serial.println(keymap[row][col]);
        int key = new_keymap[row][col];

        pixels.clear(); // Set all pixel colors to 'off'

        pixels.setPixelColor(key, pixels.Color(rand() & 150, rand() & 255, rand() & 150));

        pixels.show(); // Send the updated pixel colors to the hardware.
      }

      //  clear the EVENT IRQ flag
      keypad.writeRegister(TCA8418_REG_INT_STAT, 1);
    }

    //  check pending events
    int intstat = keypad.readRegister(TCA8418_REG_INT_STAT);
    if ((intstat & 0x03) == 0)
      TCA8418_event = false;
  }
  // other code here
  delay(100);
}
